package com.xunqi.pay.service.impl;

import com.google.gson.Gson;
import com.lly835.bestpay.enums.BestPayPlatformEnum;
import com.lly835.bestpay.enums.BestPayTypeEnum;
import com.lly835.bestpay.enums.OrderStatusEnum;
import com.lly835.bestpay.model.PayRequest;
import com.lly835.bestpay.model.PayResponse;
import com.lly835.bestpay.service.BestPayService;
import com.xunqi.pay.enums.PayPlatformEnum;
import com.xunqi.pay.mapper.PayInfoMapper;
import com.xunqi.pay.pojo.PayInfo;
import com.xunqi.pay.service.PayService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;

/**
 * @Description:
 * @Created: with IntelliJ IDEA.
 * @author: 夏沫止水
 * @createTime: 2020-05-11 17:48
 **/

@Slf4j
@Service("payService")
public class PayServiceImpl implements PayService {

    @Resource
    private BestPayService bestPayService;

    @Resource
    private PayInfoMapper payInfoMapper;

    private final static String QUEUE_PAY_NOTIFY = "payNotify";

    @Autowired
    private AmqpTemplate amqpTemplate;

    /**
     * 创建订单
     * @param orderId
     * @param amount
     * @param bestPayTypeEnum
     * @return
     */
    @Override
    public PayResponse create(String orderId, BigDecimal amount, BestPayTypeEnum bestPayTypeEnum) {

        //判断支付方式是否有误
        if (bestPayTypeEnum != BestPayTypeEnum.WXPAY_NATIVE
                && bestPayTypeEnum != BestPayTypeEnum.ALIPAY_PC) {
            throw new RuntimeException("支付方式有误！");
        }

        //先查询一下该数据库是否存在相同订单，若存在则不进行新增操作
        PayInfo pageInfoExist = payInfoMapper.selectByOrderNo(Long.valueOf(orderId));
        if (pageInfoExist == null) {
            //获取支付平台类型
            Integer code = PayPlatformEnum.getBestPlayFormEnum(bestPayTypeEnum).getCode();

            //数据赋值
            PayInfo payInfo = PayInfo.builder()
                    .orderNo(Long.valueOf(orderId))
                    .payPlatform(code)
                    .platformStatus(OrderStatusEnum.NOTPAY.name())
                    .payAmount(amount)
                    .createTime(new Date())
                    .updateTime(new Date())
                    .build();

            //添加到数据库
            payInfoMapper.insert(payInfo);
        }

        PayRequest request = new PayRequest();
        request.setOrderName("4559066-最好的支付sdk");
        request.setOrderId(orderId);
        request.setOrderAmount(amount.doubleValue());
        request.setPayTypeEnum(bestPayTypeEnum);

        PayResponse response = bestPayService.pay(request);
        response.setOrderId(orderId);
        log.info("发起支付 response={}", response);

        return response;
    }

    /**
     * 异步通知处理
     * @param notifyData
     */
    @Override
    public String asyncNotify(String notifyData) {

        //签名效验
        PayResponse payResponse = bestPayService.asyncNotify(notifyData);
        log.info("payResponse={}",payResponse);

        //2.金额效验（从数据库查订单）
        PayInfo payInfo = payInfoMapper.selectByOrderNo(Long.valueOf(payResponse.getOrderId()));

        //如果查询出来的数据是null的话
        //比较严重(正常情况下是不会发生的)发出告警：钉钉、短信
        if (payInfo == null) {
            //TODO 发出告警，钉钉，短信
            throw new RuntimeException("通过订单编号查询出来的结果是null");
        }

        //判断订单状态状态是否为已支付,如果不是订单状态不是已支付状态
        if (!payInfo.getPlatformStatus().equals(OrderStatusEnum.SUCCESS.name())) {
            //判断金额是否一致,Double类型比较大小，精度问题不好控制
            if (payInfo.getPayAmount().compareTo(BigDecimal.valueOf(payResponse.getOrderAmount())) != 0) {
                //TODO 告警
                throw new RuntimeException("异步通知中的金额和数据库里的不一致,orderNo=" + payResponse.getOrderId());
            }

            //3.修改订单支付状态
            payInfo.setPlatformStatus(OrderStatusEnum.SUCCESS.name());
            //修改更新时间
            payInfo.setUpdateTime(new Date());
            //添加交易流水号
            payInfo.setPlatformNumber(payResponse.getOutTradeNo());

            //更新到数据库中
            payInfoMapper.updateByPrimaryKeySelective(payInfo);
        }

        //TODO pay发送MQ消息，mall接收MQ消息
        //将订单信息发送给mall
        amqpTemplate.convertAndSend(QUEUE_PAY_NOTIFY,new Gson().toJson(payInfo));

        //如果支付平台是微信，则返回给异步通知给微信平台
        if (payResponse.getPayPlatformEnum() == BestPayPlatformEnum.WX) {
            //4.告诉微信不要再重复通知了
            return "<xml>\n" +
                    "  <return_code><![CDATA[SUCCESS]]></return_code>\n" +
                    "  <return_msg><![CDATA[OK]]></return_msg>\n" +
                    "</xml>";
            //如果支付平台是支付宝，则返回异步通知给支付宝平台
        } else if (payResponse.getPayPlatformEnum() == BestPayPlatformEnum.ALIPAY) {
            return "success";
        }
        //如果支付平台既不是微信也不是支付宝，直接抛出异常
        throw new RuntimeException("异步通知中错误的支付平台");
    }

    @Override
    public PayInfo queryByOrderId(String orderId) {

        log.info("查询支付记录...");
        PayInfo payInfo = payInfoMapper.selectByOrderNo(Long.valueOf(orderId));
        return payInfo;
    }
}
